home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / OpenGL / OPENGL2.EXE / _SETUP.1 / indexmat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-21  |  15.5 KB  |  608 lines

  1. /* indexmat.c */
  2.  
  3. /*
  4.  * Example/test of the GL_SGI_index_material extension
  5.  *
  6.  * This extension adds the GL_INDEX_OFFSET and GL_INDEX_SHIFT
  7.  * material parameters for CI mode lighting.  With this feature
  8.  * we can combine fog and lighting (for example) in color index
  9.  * mode.
  10.  *
  11.  * Also, we can use glEnable(GL_INDEX_MATERIAL_SGI) and
  12.  * glIndexMaterialSGI() to modify the material's GL_INDEX_OFFSET
  13.  * with the glIndex() command.  This is like glColorMaterial
  14.  * in RGB mode.
  15.  *
  16.  * This demo shows two spinning dodecahedrons using two materials
  17.  * selected via glIndex().
  18.  */
  19.  
  20. #include <assert.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <math.h>
  24. #include <windows.h>
  25. #include "GL/gl.h"
  26.  
  27. /* Have to access glIndexMaterialSGI through a pointer, ugh! */
  28. static PFNGLINDEXMATERIALSGIPROC glIndexMaterialSGIptr;
  29.  
  30. char *className = "OpenGL";
  31. char *windowName = "Index Material";
  32. int winX = 0, winY = 0;
  33. int winWidth = 300, winHeight = 300;
  34.  
  35. HDC hDC;
  36. HGLRC hGLRC;
  37. HPALETTE hPalette;
  38.  
  39. void (*idleFunc)(void);
  40.  
  41. /* Struct used to manage color ramps */
  42. struct colorIndexState {
  43.     GLfloat amb[3];    /* ambient color / bottom of ramp */
  44.     GLfloat diff[3];    /* diffuse color / middle of ramp */
  45.     GLfloat spec[3];    /* specular color / top of ramp */
  46.     GLfloat ratio;    /* ratio of diffuse to specular in ramp */
  47.     GLint indexes[3];    /* where ramp was placed in palette */
  48. };
  49.  
  50. /*
  51. ** Each entry in this array corresponds to a color ramp in the
  52. ** palette.  The indexes member of each struct is updated to
  53. ** reflect the placement of the color ramp in the palette.
  54. */
  55. #define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))
  56. struct colorIndexState colors[] = {
  57.     {
  58.         { 0.0F, 0.0F, 0.0F },    /* red */
  59.         { 1.0F, 0.0F, 0.0F },
  60.         { 1.0F, 1.0F, 1.0F },
  61.         0.75F, { 0, 0, 0 },
  62.     },
  63.     {
  64.         { 0.0F, 0.0F, 0.0F },    /* green */
  65.         { 0.0F, 1.0F, 0.0F },
  66.         { 1.0F, 1.0F, 1.0F },
  67.         0.75F, { 0, 0, 0 },
  68.     },
  69. };
  70.  
  71. static GLfloat Yrot = 0.0F;
  72.  
  73. static GLboolean
  74. checkExtension(const char *name)
  75. {
  76.     const char *p = (const char *) glGetString(GL_EXTENSIONS);
  77.  
  78.     while (p = strstr(p, name)) {
  79.     const char *q = p + strlen(name);
  80.  
  81.     if (*q == ' ' || *q == '\0') {
  82.         return GL_TRUE;
  83.     }
  84.     p = q;
  85.     }
  86.     return GL_FALSE;
  87. }
  88.  
  89. static void
  90. checkError(char *msg)
  91. {
  92.     GLenum err;
  93.  
  94.     while ((err = glGetError()) != GL_NO_ERROR) {
  95.     printf("Error %d at %s\n", err, msg);
  96.     }
  97. }
  98.  
  99. static void
  100. init(void)
  101. {
  102.     GLfloat spec[4] = {0.2F, 0.2F, 0.2F, 1.0F};
  103.     GLfloat dif[4]  = {0.8F, 0.8F, 0.8F, 1.0F};
  104.     GLfloat amb[4]  = {0.2F, 0.2F, 0.2F, 1.0F};
  105.     GLint indexes[3];
  106.     GLint i;
  107.  
  108.     /* Note: indexes are zero based */
  109.     indexes[0] = 0;
  110.     indexes[1] = colors[0].indexes[1] - colors[0].indexes[0];
  111.     indexes[2] = colors[0].indexes[2] - colors[0].indexes[0];
  112.  
  113.     glMaterialiv( GL_FRONT_AND_BACK, GL_COLOR_INDEXES, indexes );
  114.  
  115.     glLightfv( GL_LIGHT0, GL_DIFFUSE, dif );
  116.     glLightfv( GL_LIGHT0, GL_AMBIENT, amb );
  117.     glLightfv( GL_LIGHT0, GL_SPECULAR, spec );
  118.  
  119.     glEnable(GL_LIGHTING);
  120.     glEnable(GL_LIGHT0);
  121.  
  122.     glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, 1 );
  123.  
  124.     /* index material stuff */
  125.     glIndexMaterialSGIptr = (void *) wglGetProcAddress("glIndexMaterialSGI");
  126.     if (!glIndexMaterialSGIptr) {
  127.         printf("Error: renderer doesn't support GL_SGI_index_material\n");
  128.         exit(1);
  129.     }
  130.  
  131.     /* front and back index offset tracks glIndex(): */
  132.     (*glIndexMaterialSGIptr)( GL_FRONT_AND_BACK, GL_INDEX_OFFSET );
  133.     glEnable( GL_INDEX_MATERIAL_SGI );
  134.  
  135.     /* test attrib pushing/popping */
  136.     glPushAttrib( GL_LIGHTING_BIT );
  137.     glDisable( GL_INDEX_MATERIAL_SGI );
  138.     (*glIndexMaterialSGIptr)( GL_BACK, GL_INDEX_OFFSET );
  139.     glPopAttrib();
  140.  
  141.     glGetIntegerv( GL_INDEX_MATERIAL_FACE_SGI, &i );
  142.     assert( i==GL_FRONT_AND_BACK );
  143.     glGetIntegerv( GL_INDEX_MATERIAL_PARAMETER_SGI, &i );
  144.     assert( i==GL_INDEX_OFFSET );
  145.     assert( glIsEnabled(GL_INDEX_MATERIAL_SGI) );
  146.  
  147.     /* temporary:
  148.     glMateriali( GL_FRONT_AND_BACK, GL_INDEX_SHIFT, -1 );
  149.     glCullFace( GL_FRONT );
  150.     */
  151.  
  152.     glEnable( GL_DEPTH_TEST );
  153.     checkError("Checkpoint");
  154. }
  155.  
  156. void
  157. drawDodecahedron(void)
  158. {
  159. #define A (1.61803F)    /* (sqrt(5) + 1) / 2 */
  160. #define B (0.61803F)    /* (sqrt(5) - 1) / 2 */
  161. #define C (1.0F)
  162.     GLfloat vertexes[20][3] = {
  163.     {-A, 0.0F, B }, {-A, 0.0F,-B }, { A, 0.0F,-B }, { A, 0.0F, B },
  164.     { B,-A, 0.0F }, {-B,-A, 0.0F }, {-B, A, 0.0F }, { B, A, 0.0F },
  165.     { 0.0F, B,-A }, { 0.0F,-B,-A }, { 0.0F,-B, A }, { 0.0F, B, A },
  166.     {-C,-C, C }, {-C,-C,-C }, { C,-C,-C }, { C,-C, C },
  167.     {-C, C, C }, {-C, C,-C }, { C, C,-C }, { C, C, C },
  168.     };
  169. #undef A
  170. #undef B
  171. #undef C
  172.     GLint polygons[12][5] = {
  173.     {  0, 12, 10, 11, 16 },
  174.     {  1, 17,  8,  9, 13 },
  175.     {  2, 14,  9,  8, 18 },
  176.     {  3, 19, 11, 10, 15 },
  177.     {  4, 14,  2,  3, 15 },
  178.     {  5, 12,  0,  1, 13 },
  179.     {  6, 17,  1,  0, 16 },
  180.     {  7, 19,  3,  2, 18 },
  181.     {  8, 17,  6,  7, 18 },
  182.     {  9, 14,  4,  5, 13 },
  183.     { 10, 12,  5,  4, 15 },
  184.     { 11, 19,  7,  6, 16 },
  185.     };
  186.     int i;
  187.  
  188.     for (i=0; i<12; ++i) {
  189.     GLfloat *p0, *p1, *p2, d;
  190.     GLfloat u[3], v[3], n[3];
  191.  
  192.     p0 = &vertexes[polygons[i][0]][0];
  193.     p1 = &vertexes[polygons[i][1]][0];
  194.     p2 = &vertexes[polygons[i][2]][0];
  195.  
  196.     u[0] = p2[0] - p1[0];
  197.     u[1] = p2[1] - p1[1];
  198.     u[2] = p2[2] - p1[2];
  199.  
  200.     v[0] = p0[0] - p1[0];
  201.     v[1] = p0[1] - p1[1];
  202.     v[2] = p0[2] - p1[2];
  203.  
  204.     n[0] = u[1]*v[2] - u[2]*v[1];
  205.     n[1] = u[2]*v[0] - u[0]*v[2];
  206.     n[2] = u[0]*v[1] - u[1]*v[0];
  207.  
  208.     d = 1.0F / (GLfloat) sqrt(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
  209.     n[0] *= d;
  210.     n[1] *= d;
  211.     n[2] *= d;
  212.  
  213.     glBegin(GL_POLYGON);
  214.     glNormal3fv(n);
  215.     glVertex3fv(p0);
  216.     glVertex3fv(p1);
  217.     glVertex3fv(p2);
  218.     glVertex3fv(vertexes[polygons[i][3]]);
  219.     glVertex3fv(vertexes[polygons[i][4]]);
  220.     glEnd();
  221.     }
  222. }
  223.  
  224. static void
  225. redraw(void)
  226. {
  227.     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  228.  
  229.     glPushMatrix();
  230.     glTranslatef( -2.0F, 0.0F, 0.0F );
  231.     glRotatef( Yrot, 0.0F, 1.0F, 0.0F );
  232.     /* Select the material via glIndex */
  233.     glIndexi( colors[0].indexes[0] );
  234.     /*OR glMateriali( GL_FRONT_AND_BACK, GL_INDEX_OFFSET, colors[0].indexes[0] );*/
  235.     drawDodecahedron();
  236.     glPopMatrix();
  237.  
  238.     glPushMatrix();
  239.     glTranslatef( 2.0F, 0.0F, 0.0F );
  240.     glRotatef( Yrot, 0.0F, 1.0F, 0.0F );
  241.     /* Select the material via glIndex */
  242.     glIndexi( colors[1].indexes[0] );
  243.     /*OR glMateriali( GL_FRONT_AND_BACK, GL_INDEX_OFFSET, colors[1].indexes[0] );*/
  244.     drawDodecahedron();
  245.     glPopMatrix();
  246.  
  247.     SwapBuffers(hDC);
  248. }
  249.  
  250. static void
  251. idleRedraw(void)
  252. {
  253.     Yrot += 2.0f;
  254.     redraw();
  255. }
  256.  
  257. static void
  258. resize(void)
  259. {
  260.     glViewport( 0, 0, winWidth, winHeight );
  261.     glMatrixMode( GL_PROJECTION );
  262.     glLoadIdentity();
  263.     glFrustum( -2.0F, 2.0F, -2.0F, 2.0F, 5.0F, 25.0F );
  264.     glMatrixMode( GL_MODELVIEW );
  265.     glLoadIdentity();
  266.     glTranslatef( 0.0F, 0.0F, -15.0F );
  267. }
  268.  
  269. /*****************************************************************/
  270.  
  271. void
  272. setupPalette(HDC hDC)
  273. {
  274.     PIXELFORMATDESCRIPTOR pfd;
  275.     LOGPALETTE* pPal;
  276.     int pixelFormat = GetPixelFormat(hDC);
  277.     int paletteSize;
  278.  
  279.     DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  280.  
  281.     /*
  282.     ** Determine if a palette is needed and if so what size.
  283.     */
  284.     if (pfd.dwFlags & PFD_NEED_PALETTE ||
  285.         pfd.iPixelType == PFD_TYPE_COLORINDEX) {
  286.     paletteSize = 1 << pfd.cColorBits;
  287.     if (paletteSize > 4096) {
  288.         paletteSize = 4096;
  289.     }
  290.     } else {
  291.     return;
  292.     }
  293.  
  294.     pPal = (LOGPALETTE*)
  295.     malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
  296.     pPal->palVersion = 0x300;
  297.     pPal->palNumEntries = paletteSize;
  298.  
  299.     /*
  300.     ** Fill the logical palette with color ramps.
  301.     **
  302.     ** Set up the logical palette so that it can be realized
  303.     ** into the system palette as an identity palette.
  304.     **
  305.     ** 1) The default static entries should be present and at the right
  306.     **    location.  The easiest way to do this is to grab them from
  307.     **    the current system palette.
  308.     **
  309.     ** 2) All non-static entries should be initialized to unique values.
  310.     **    The easiest way to do this is to ensure that all of the non-static
  311.     **    entries have the PC_NOCOLLAPSE flag bit set.
  312.     */
  313.     {
  314.     int numRamps = NUM_COLORS;
  315.     int rampSize = (paletteSize - 20) / numRamps;
  316.     int extra = (paletteSize - 20) - (numRamps * rampSize);
  317.     int i, r;
  318.  
  319.     /*
  320.     ** Initialize static entries by copying them from the
  321.     ** current system palette.
  322.     */
  323.     GetSystemPaletteEntries(hDC, 0, paletteSize, &pPal->palPalEntry[0]);
  324.  
  325.     /*
  326.     ** Fill in non-static entries with desired colors.
  327.     */
  328.     for (r=0; r<numRamps; ++r) {
  329.         int rampBase = r * rampSize + 10;
  330.         PALETTEENTRY *pe = &pPal->palPalEntry[rampBase];
  331.         int diffSize = (int) (rampSize * colors[r].ratio);
  332.         int specSize = rampSize - diffSize;
  333.  
  334.         for (i=0; i<rampSize; ++i) {
  335.         GLfloat *c0, *c1;
  336.         GLint a;
  337.  
  338.         if (i < diffSize) {
  339.             c0 = colors[r].amb;
  340.             c1 = colors[r].diff;
  341.             a = (i * 255) / (diffSize - 1);
  342.         } else {
  343.             c0 = colors[r].diff;
  344.             c1 = colors[r].spec;
  345.             a = ((i - diffSize) * 255) / (specSize - 1);
  346.         }
  347.  
  348.         pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]);
  349.         pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]);
  350.         pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]);
  351.         pe[i].peFlags = PC_NOCOLLAPSE;
  352.         }
  353.  
  354.         colors[r].indexes[0] = rampBase;
  355.         colors[r].indexes[1] = rampBase + (diffSize-1);
  356.         colors[r].indexes[2] = rampBase + (rampSize-1);
  357.     }
  358.  
  359.     /*
  360.     ** Initialize any remaining non-static entries.
  361.     */
  362.     for (i=0; i<extra; ++i) {
  363.         int index = numRamps*rampSize+10+i;
  364.         PALETTEENTRY *pe = &pPal->palPalEntry[index];
  365.  
  366.         pe->peRed = (BYTE) 0;
  367.         pe->peGreen = (BYTE) 0;
  368.         pe->peBlue = (BYTE) 0;
  369.         pe->peFlags = PC_NOCOLLAPSE;
  370.     }
  371.     }
  372.  
  373.     hPalette = CreatePalette(pPal);
  374.     free(pPal);
  375.  
  376.     if (hPalette) {
  377.     SelectPalette(hDC, hPalette, FALSE);
  378.     RealizePalette(hDC);
  379.     }
  380. }
  381.  
  382. void
  383. setupPixelFormat(HDC hDC)
  384. {
  385.     PIXELFORMATDESCRIPTOR pfd = {
  386.     sizeof(PIXELFORMATDESCRIPTOR),    /* size of this pfd */
  387.     1,                /* version num */
  388.     PFD_DRAW_TO_WINDOW |        /* support window */
  389.     PFD_SUPPORT_OPENGL |        /* support OpenGL */
  390.     PFD_DOUBLEBUFFER,        /* support double-buffering */
  391.     PFD_TYPE_COLORINDEX,        /* color index mode */
  392.     8,                /* 8-bit color depth */
  393.     0, 0, 0, 0, 0, 0,        /* color bits (ignored) */
  394.     0,                /* no alpha buffer */
  395.     0,                /* alpha bits (ignored) */
  396.     0,                /* no accumulation buffer */
  397.     0, 0, 0, 0,            /* accum bits (ignored) */
  398.     16,                /* depth buffer */
  399.     0,                /* no stencil buffer */
  400.     0,                /* no auxiliary buffers */
  401.     PFD_MAIN_PLANE,            /* main layer */
  402.     0,                /* reserved */
  403.     0, 0, 0,            /* no layer, visible, damage masks */
  404.     };
  405.     int SelectedPixelFormat;
  406.     BOOL retVal;
  407.  
  408.     SelectedPixelFormat = ChoosePixelFormat(hDC, &pfd);
  409.     if (SelectedPixelFormat == 0) {
  410.     MessageBox(WindowFromDC(hDC),
  411.         "ChoosePixelFormat failed\n"
  412.         "This application works best with an 8-bit\n"
  413.         "(256 color) display mode\n",
  414.         "Error",
  415.         MB_ICONERROR | MB_OK);
  416.     exit(1);
  417.     }
  418.  
  419.     retVal = SetPixelFormat(hDC, SelectedPixelFormat, &pfd);
  420.     if (retVal != TRUE) {
  421.     MessageBox(WindowFromDC(hDC), "SetPixelFormat failed", "Error",
  422.         MB_ICONERROR | MB_OK);
  423.     exit(1);
  424.     }
  425. }
  426.  
  427. LRESULT APIENTRY
  428. WndProc(
  429.     HWND hWnd,
  430.     UINT message,
  431.     WPARAM wParam,
  432.     LPARAM lParam)
  433. {
  434.     switch (message) {
  435.     case WM_CREATE:
  436.     /*
  437.     ** Set up for OpenGL rendering.  Bind the rendering context to
  438.     ** the same device context that the palette will be selected into.
  439.     */
  440.     hDC = GetDC(hWnd);
  441.     setupPixelFormat(hDC);
  442.     setupPalette(hDC);
  443.     hGLRC = wglCreateContext(hDC);
  444.     wglMakeCurrent(hDC, hGLRC);
  445.     if (!checkExtension("SGI_index_material")) {
  446.         char message[1024];
  447.  
  448.         sprintf(message,
  449.         "SGI_index_material is required by this application\n"
  450.         "but is not supported by the current OpenGL renderer.\n\n"
  451.         "Vendor: %s\nRenderer: %s\nVersion: %s",
  452.         glGetString(GL_VENDOR),
  453.         glGetString(GL_RENDERER),
  454.         glGetString(GL_VERSION));
  455.  
  456.         wglMakeCurrent(NULL, NULL);
  457.         wglDeleteContext(hGLRC);
  458.         hGLRC = NULL;
  459.  
  460.         MessageBox(hWnd, message, "OpenGL Extension Required",
  461.             MB_ICONERROR | MB_OK);
  462.         exit(1);
  463.     }
  464.     init();
  465.     idleFunc = idleRedraw;
  466.     return 0;
  467.     case WM_DESTROY:
  468.     /*
  469.     ** Finish OpenGL rendering.
  470.     */
  471.     idleFunc = NULL;
  472.     if (hGLRC) {
  473.         wglMakeCurrent(NULL, NULL);
  474.         wglDeleteContext(hGLRC);
  475.     }
  476.     ReleaseDC(hWnd, hDC);
  477.     PostQuitMessage(0);
  478.     return 0;
  479.     case WM_SIZE:
  480.     if (hGLRC) {
  481.         winWidth = (int) LOWORD(lParam);
  482.         winHeight = (int) HIWORD(lParam);
  483.         resize();
  484.         return 0;
  485.     }
  486.     case WM_PALETTECHANGED:
  487.     /*
  488.     ** Update palette mapping if this *is not* the active window.
  489.     */
  490.     if (hGLRC && hPalette && (HWND) wParam != hWnd) {
  491.         UnrealizeObject(hPalette);
  492.         SelectPalette(hDC, hPalette, FALSE);
  493.         RealizePalette(hDC);
  494.         redraw();
  495.         return 0;
  496.     }
  497.     break;
  498.     case WM_QUERYNEWPALETTE:
  499.     /*
  500.     ** Update palette mapping if this *is* the active window.
  501.     */
  502.     if (hGLRC && hPalette) {
  503.         UnrealizeObject(hPalette);
  504.         SelectPalette(hDC, hPalette, FALSE);
  505.         RealizePalette(hDC);
  506.         redraw();
  507.         return TRUE;
  508.     }
  509.     break;
  510.     case WM_PAINT:
  511.     /*
  512.     ** Update the window.  Don't use the device context returned by
  513.     ** BeginPaint as it won't have the right palette selected into it.
  514.     */
  515.     if (hGLRC) {
  516.         PAINTSTRUCT ps;
  517.  
  518.         BeginPaint(hWnd, &ps);
  519.         redraw();
  520.         EndPaint(hWnd, &ps);
  521.         return 0;
  522.     }
  523.     break;
  524.     case WM_CHAR:
  525.     switch ((int)wParam) {
  526.     case VK_ESCAPE:
  527.         DestroyWindow(hWnd);
  528.         return 0;
  529.     default:
  530.         break;
  531.     }
  532.     break;
  533.     default:
  534.     break;
  535.     }
  536.  
  537.     /* Deal with any unprocessed messages */
  538.     return DefWindowProc(hWnd, message, wParam, lParam);
  539. }
  540.  
  541. int APIENTRY
  542. WinMain(
  543.     HINSTANCE hCurrentInst,
  544.     HINSTANCE hPreviousInst,
  545.     LPSTR lpszCmdLine,
  546.     int nCmdShow)
  547. {
  548.     WNDCLASS wndClass;
  549.     HWND hWnd;
  550.     MSG msg;
  551.  
  552.     /* Define and register a window class */
  553.     wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  554.     wndClass.lpfnWndProc = WndProc;
  555.     wndClass.cbClsExtra = 0;
  556.     wndClass.cbWndExtra = 0;
  557.     wndClass.hInstance = hCurrentInst;
  558.     wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  559.     wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  560.     wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
  561.     wndClass.lpszMenuName = NULL;
  562.     wndClass.lpszClassName = className;
  563.     RegisterClass(&wndClass);
  564.  
  565.     /* Figure out a default size for the window */
  566.     winWidth = GetSystemMetrics(SM_CYSCREEN) / 3;
  567.     winHeight = GetSystemMetrics(SM_CYSCREEN) / 3;
  568.  
  569.     /* Create a window of the previously defined class */
  570.     hWnd = CreateWindow(
  571.     className,        /* Window class's name */
  572.     windowName,        /* Title bar text */
  573.     WS_OVERLAPPEDWINDOW |    /* The window's style */
  574.     WS_CLIPCHILDREN |
  575.     WS_CLIPSIBLINGS,
  576.     winX, winY,        /* Position */
  577.     winWidth, winHeight,    /* Size */
  578.     NULL,            /* Parent window's handle */
  579.     NULL,            /* Menu handle */
  580.     hCurrentInst,        /* Instance handle */
  581.     NULL);            /* No additional data */
  582.  
  583.     /* Map the window to the screen */
  584.     ShowWindow(hWnd, nCmdShow);
  585.  
  586.     /* Force the window to repaint itself */
  587.     UpdateWindow(hWnd);
  588.  
  589.     /* Process Messages */
  590.     while (1) {
  591.     /* execute the idle function while there are no messages to process */
  592.     while (idleFunc &&
  593.            PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == FALSE)
  594.     {
  595.         (*idleFunc)();
  596.     }
  597.     if (GetMessage(&msg, NULL, 0, 0) != TRUE) {
  598.         break;
  599.     }
  600.     TranslateMessage(&msg);
  601.     DispatchMessage(&msg);
  602.     }
  603.  
  604.     return msg.wParam;
  605. }
  606.  
  607. 
  608.